﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ComunesMGI.DataTypes;
using System.IO;
using ComunesMGI.Enums;
using ComunesMGI.Excepciones;
using ComunesMGI.Condiciones;

namespace MGI.Logica
{
    class CtrIncidentes : IIncidentes
    {

        #region IIncidentes Members


        public void EliminarTarea(int idSistema, int idTarea)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);


            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataEliminarTarea dataTarea = mgrIncidentes.EliminarTarea(dataSistema.Sitio, idTarea, dataSistema.UrlWS);

            //se deben pasar todos los datos para enviar el mail
            if (dataTarea.TieneResponsable)
            {
                MgrUsuarios.GetInstance().EnviarMailEliminarTarea(dataTarea, dataSistema);
            }
        }

        public void EliminarIncidente(int idSistema, int idIncidente)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            List<DataTarea> tareas = mgrIncidentes.GetTareas(dataSistema.Sitio, idIncidente, dataSistema.UrlWS);
            if (tareas.Count > 0)
            {
                throw new CondicionInvalidaException("El incidente a eliminar tiene aún tareas asociadas");
            }
            else
            {
                mgrIncidentes.EliminarIncidente(dataSistema.Sitio, idIncidente, dataSistema.UrlWS);
            }
        }



        public void DesasociarIncidentesWP(int idWP, List<int> incidentes)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataWP dtWP = mgrIncidentes.GetWorkPackage(idWP);

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(dtWP.IdSistema);

            mgrIncidentes.DesasociarIncidentesWP(dataSistema.Sitio, incidentes, dataSistema.UrlWS);
        }

        public List<DataCampo> GetCampos(int idSistema, Lista lista)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrClientes mgrCliente = MgrClientes.GetInstance();
            DataCliente dataCliente = mgrCliente.GetCliente(dataSistema.CodCliente);

            if (mgrCliente.ContainFileCliente(dataCliente.Nombre))
            {
                if (mgrSistemas.ContainFileSistema(dataCliente.Nombre, dataSistema.Nombre))
                {
                    MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
                    List<DataCampo> nomCampos = mgrIncidentes.GetCamposXML(dataCliente.Nombre, dataSistema.Nombre, lista);
                    List<DataCampo> campos = mgrIncidentes.GetCamposSharepoint(dataSistema.Sitio, lista, nomCampos, dataSistema.UrlWS);
                    foreach (DataCampo dataCampo in campos)
                    {
                        if (dataCampo.Tipo == CampoSharepoint.User)
                        {
                            MgrUsuarios mgrUsuarios = MgrUsuarios.GetInstance();
                            List<DataUsuario> usuarios = mgrUsuarios.GetUsuarios();
                            List<string> nomUsuarios = new List<string>();
                            foreach (DataUsuario usuario in usuarios)
                            {
                                nomUsuarios.Add(usuario.Nombre);
                            }
                            dataCampo.Opciones = nomUsuarios;
                        }
                    }
                    return campos;
                }
                else
                {
                    throw new Exception("No existe archivo xml de mapeo de los campos para el sistema en la carpeta del cliente");
                }
            }
            else
            {
                throw new Exception("No existe carpeta para el cliente del sistema");
            }

        }

        public DataAltaIncidente AddIncidente(DataSistema incidente)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.AddIncidente(incidente);
        }

        public List<DataIncidente> GetIncidentes(int idSistema, List<Condicion> condiciones)
        {

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetIncidentes(dataSistema.Sitio, condiciones, dataSistema.UrlWS);
        }

        public List<DataIncidente> GetIncidentesAsignablesWP(int wkpCod)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataWP dataWP = mgrIncidentes.GetWorkPackage(wkpCod);
            int idSistema = dataWP.IdSistema;

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            return mgrIncidentes.GetIncidentesAsignablesWP(dataSistema.Sitio, wkpCod, dataSistema.UrlWS, dataWP.FechaEstimadaEntrega);

        }

        public List<DataTarea> GetTareas(int idSistema, int idIncidente)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetTareas(dataSistema.Sitio, idIncidente, dataSistema.UrlWS);
        }

        public DataTareaConCampos GetTarea(int idSistema, int idTarea)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrClientes mgrClientes = MgrClientes.GetInstance();
            DataCliente dataCliente = mgrClientes.GetCliente(dataSistema.CodCliente);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            List<DataCampo> campos = mgrIncidentes.GetCamposXML(dataCliente.Nombre, dataSistema.Nombre, Lista.Tareas);
            DataTareaConCampos tarea = mgrIncidentes.GetTarea(dataSistema.Sitio, idTarea, campos, dataSistema.UrlWS);

            foreach (DataCampo dataCampo in tarea.Campos)
            {
                if (dataCampo.Tipo == CampoSharepoint.User)
                {
                    MgrUsuarios mgrUsuarios = MgrUsuarios.GetInstance();
                    List<DataUsuario> usuarios = mgrUsuarios.GetUsuarios();
                    List<string> nomUsuarios = new List<string>();
                    foreach (DataUsuario usuario in usuarios)
                    {
                        nomUsuarios.Add(usuario.Nombre);
                    }
                    dataCampo.Opciones = nomUsuarios;
                }
            }
            return tarea;

        }

        public bool AsignarResponsable(int idSistema, int idIncidente, DataTarea tarea, DataUsuario usuario)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            string mail = mgrIncidentes.AsignarResponsable(dataSistema.Sitio, idIncidente, Int32.Parse(tarea.IdTarea), usuario, dataSistema.UrlWS);

            //se obtienen todos los datos de la tarea para enviar el mail
            DataTareaConCampos dataTarea = GetTarea(idSistema, int.Parse(tarea.IdTarea));
            return MgrUsuarios.GetInstance().EnviarMailAsignarTarea(mail, dataTarea);
        }

        public int AddWorkPackage(int idSistema, DataWP workPackage)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.AddWorkPackage(idSistema, workPackage);
        }

        public List<DataWP> GetWorkPackages(int sisCod)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(sisCod);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetWorkPackages(dataSistema);

        }

        public void AsociarIncidentesWP(int idSistema, int idWorkPackage, List<int> incidentes)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            mgrIncidentes.AsociarIncidentesWP(dataSistema.Sitio, idWorkPackage, incidentes, dataSistema.UrlWS);
        }


        public List<DataIncidenteReporte> GetIncidentesCerradosPeriodo(List<int> sistemas, DateTime perFchIni, DateTime perFchFin)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            List<DataSistema> datosSistemas = new List<DataSistema>();
            if (sistemas.Count() == 0)
            {
                MgrClientes mgrCliente = MgrClientes.GetInstance();
                List<DataCliente> clientes = mgrCliente.GetClientes();
                foreach (DataCliente cli in clientes)
                {
                    List<DataSistema> _sistemasCliente = mgrSistemas.GetSistemas(cli.Codigo);
                    foreach (DataSistema _sdc in _sistemasCliente)
                    {
                        sistemas.Add(_sdc.Codigo);
                    }
                }

            }
            foreach (int codSistema in sistemas)
            {
                datosSistemas.Add(mgrSistemas.GetSistema(codSistema));
            }
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetIncidentesCerradosPeriodo(datosSistemas, perFchIni, perFchFin);
        }

        public List<DataIncidente> GetIncidentesWP(int idSistema, int idWorkPackage)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetIncidentesWP(dataSistema.Sitio, idWorkPackage, dataSistema.UrlWS);
        }

        public bool AdjuntarArchivoIncidente(string nombreArchivo, int idSistema, int idIncidente, string nroTemp)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrArchivos mgrArchivos = MgrArchivos.GetInstance();

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            Stream archivo = mgrArchivos.ObtenerArchivo(nroTemp);
            string temporalArchivo = mgrIncidentes.UploadFile(archivo, dataSistema.UrlWS);

            bool retorno = mgrIncidentes.AdjuntarArchivoIncidente(nombreArchivo, dataSistema.Sitio, idIncidente, temporalArchivo, dataSistema.UrlWS);
            archivo.Close();
            mgrArchivos.BorrarArchivo(nroTemp);
            return retorno;

        }


        public DataAltaTarea AddTarea(int idSistema, int idIncidente, List<DataCampo> campos)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            DataCampo campoOculto = new DataCampo("IDOriginal", ParteMail.Ninguno);
            campoOculto.Valor = idIncidente.ToString();
            campos.Add(campoOculto);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataAltaTarea tarea = mgrIncidentes.AddTarea(dataSistema.Sitio, campos, dataSistema.UrlWS);
            //si le asignaron responsable se le envía mail al responsable
            if (!String.IsNullOrEmpty(tarea.Mail))
            {
                DataTareaConCampos tareaConCampos = new DataTareaConCampos(tarea.IdTarea, "", campos);
                MgrUsuarios.GetInstance().EnviarMailAsignarTarea(tarea.Mail, tareaConCampos);
            }
            return tarea;
        }

        public string UploadFile(Stream sourceStream)
        {
            MgrArchivos mgrArchivos = MgrArchivos.GetInstance();
            return mgrArchivos.UploadFile(sourceStream);
        }

        public List<DataEstadoWP> GetEstadosWP()
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetEstadosWP();
        }

        public List<DataIncidenteReporte> VisualizarIncidentesAsignados(List<int> sistemas, string usuario, string estado, DateTime perFchIni, DateTime perFchFin)
        {

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            List<DataSistema> datosSistemas = new List<DataSistema>();
            if (sistemas.Count() == 0)
            {
                MgrClientes mgrCliente = MgrClientes.GetInstance();
                List<DataCliente> clientes = mgrCliente.GetClientes();
                foreach (DataCliente cli in clientes)
                {
                    List<DataSistema> _sistemasCliente = mgrSistemas.GetSistemas(cli.Codigo);
                    foreach (DataSistema _sdc in _sistemasCliente)
                    {
                        sistemas.Add(_sdc.Codigo);
                    }
                }
            }
            foreach (int codSistema in sistemas)
            {
                datosSistemas.Add(mgrSistemas.GetSistema(codSistema));
            }
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.VisualizarIncidentesAsignados(datosSistemas, usuario, estado, perFchIni, perFchFin);
        }


        public bool ChkWpIncidentesOTareasSinCerrar(int wkpCod)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataWP dataWP = mgrIncidentes.GetWorkPackage(wkpCod);
            int idSistema = dataWP.IdSistema;

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            return mgrIncidentes.ChkWpIncidentesOTareasSinCerrar(dataSistema.Sitio, wkpCod, dataSistema.UrlWS);
        }


        public List<DataIncidenteReporte> GetIncidentesCreadosPeriodo(List<int> sistemas, DateTime perFchIni, DateTime perFchFin)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            List<DataSistema> datosSistemas = new List<DataSistema>();
            if (sistemas.Count() == 0)
            {
                MgrClientes mgrCliente = MgrClientes.GetInstance();
                List<DataCliente> clientes = mgrCliente.GetClientes();
                foreach (DataCliente cli in clientes)
                {
                    List<DataSistema> _sistemasCliente = mgrSistemas.GetSistemas(cli.Codigo);
                    foreach (DataSistema _sdc in _sistemasCliente)
                    {
                        sistemas.Add(_sdc.Codigo);
                    }
                }

            }
            foreach (int codSistema in sistemas)
            {
                datosSistemas.Add(mgrSistemas.GetSistema(codSistema));
            }
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetIncidentesCreadosPeriodo(datosSistemas, perFchIni, perFchFin);
        }



        public void ModificarWP(DataWP wp, bool cerrarTodo)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            int idSistema = wp.IdSistema;

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            DataWP estadoPrevio = mgrIncidentes.GetWorkPackage(wp.Id);
            bool cumpleCondFechas = mgrIncidentes.IsFechaEstimadaEntregaWPMayorIncidentes(dataSistema.Sitio, wp.Id, wp.FechaEstimadaEntrega, dataSistema.UrlWS);
            if (cumpleCondFechas)
            {
                mgrIncidentes.ModificarWP(wp);
                if (wp.Estado.Final && cerrarTodo)
                {
                    try
                    {
                        mgrIncidentes.CerrarAsociadosWP(dataSistema.Sitio, wp.Id, dataSistema.UrlWS);
                    }
                    catch (Exception)
                    {
                        mgrIncidentes.ModificarWP(estadoPrevio);
                        throw new SPConeccionFallidaException("Error en SharePoint, no se han realizado los cambios");
                    }
                }
            }
            else
            {
                throw new Exception("La fecha estimada de entrega del work package debe ser menor o igual a las fechas estimadas de cierre de los incidentes del work package");
            }
        }

        public DataIncidenteConCampos GetIncidente(int idIncidente, int idSistema)
        {

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);

            MgrClientes mgrClientes = MgrClientes.GetInstance();
            DataCliente dataCliente = mgrClientes.GetCliente(dataSistema.CodCliente);

            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();

            List<DataCampo> campos = mgrIncidentes.GetCamposXML(dataCliente.Nombre, dataSistema.Nombre, Lista.Incidentes);

            DataIncidenteConCampos dataIncidente = mgrIncidentes.GetIncidente(idIncidente, dataSistema.Sitio, campos, dataSistema.UrlWS);

            foreach (DataCampo dataCampo in dataIncidente.Campos)
            {
                if (dataCampo.Tipo == CampoSharepoint.User)
                {
                    MgrUsuarios mgrUsuarios = MgrUsuarios.GetInstance();
                    List<DataUsuario> usuarios = mgrUsuarios.GetUsuarios();
                    List<string> nomUsuarios = new List<string>();
                    foreach (DataUsuario usuario in usuarios)
                    {
                        nomUsuarios.Add(usuario.Nombre);
                    }
                    dataCampo.Opciones = nomUsuarios;
                }
            }

            return dataIncidente;

        }

        public void ModificarTarea(int idSistema, DataTareaConCampos tarea)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            DataEliminarTarea dataTarea = mgrIncidentes.ModificarTarea(dataSistema.Sitio, tarea, dataSistema.UrlWS);

            //se deben pasar todos los datos para enviar el mail
            if (dataTarea.TieneResponsable)
            {
                MgrUsuarios.GetInstance().EnviarMailModificarTarea(dataTarea, dataSistema);
            }
        }

        public void ModificarIncidente(int idSistema, DataIncidenteConCampos incidente)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            mgrIncidentes.ModificarIncidente(dataSistema.Sitio, incidente, dataSistema.UrlWS);
        }

        public List<DataWPReporte> GetWorkPackagesDadosAltaPeriodo(List<int> sistemas, DateTime perFchIni, DateTime perFchFin)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            List<DataWPReporte> listaReporte = new List<DataWPReporte>();
            if (sistemas.Count() > 0)
            {
                foreach (int idSistema in sistemas)
                {
                    List<DataWPReporte> wps = mgrIncidentes.GetWorkPackagesDadosAltaPeriodo(idSistema, perFchIni, perFchFin);
                    listaReporte.AddRange(wps);
                }
            }
            else //si la lista de sistemas es null tengo que devolver los wp de todos los wp existentes
            {
                MgrClientes mgrClientes = MgrClientes.GetInstance();
                MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
                List<DataSistema> sistemasTodos = new List<DataSistema>();
                List<DataCliente> clientes = mgrClientes.GetClientes();
                foreach (DataCliente cliente in clientes)
                {
                    List<DataSistema> sistemasCliente = mgrSistemas.GetSistemas(cliente.Codigo);
                    sistemasTodos.AddRange(sistemasCliente);
                }
                foreach (DataSistema sistema in sistemasTodos)
                {
                    List<DataWPReporte> wps = mgrIncidentes.GetWorkPackagesDadosAltaPeriodo(sistema.Codigo, perFchIni, perFchFin);
                    listaReporte.AddRange(wps);
                }
            }
            return listaReporte;

        }

        public List<string> GetEstadosIncidentes(int idSistema)
        {
            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();
            return mgrIncidentes.GetEstadosIncidentes(dataSistema.Sitio, dataSistema.UrlWS);
        }


        public void EliminarWorkPackage(int idWP)
        {
            MgrIncidentes mgrIncidentes = MgrIncidentes.GetInstance();

            DataWP dataWP = mgrIncidentes.GetWorkPackage(idWP);
            int idSistema = dataWP.IdSistema;

            MgrSistemas mgrSistemas = MgrSistemas.GetInstance();
            DataSistema dataSistema = mgrSistemas.GetSistema(idSistema);
            List<DataIncidente> incidentes = mgrIncidentes.GetIncidentesWP(dataSistema.Sitio, idWP, dataSistema.UrlWS);
            if (incidentes.Count > 0)
            {
                throw new Exception("No es posible eliminar el work package porque tiene incidentes asignados");

            }
            mgrIncidentes.EliminarWorkPackage(idWP);
        }

        #endregion
    }
}
